remotes::install_github("nsgrantham/ggbraid")1 The task
In this take-home exercise, you are required to uncover the impact of COVID-19 as well as the global economic and political dynamic in 2022 on Singapore bi-lateral trade (i.e. Import, Export and Trade Balance) by using appropriate analytical visualisation techniques learned in Lesson 6: It’s About Time. Students are encouraged to apply appropriate interactive techniques to enhance user and data discovery experiences.
2 Introduction
In 2020, Singapore was the 36th largest economy in terms of GDP, the 19th largest in terms of total exports, the 17th largest in terms of total imports, the 11th largest in terms of GDP per capita, and the sixth most complex economy according to the Economic Complexity Index (ECI).
Since 2016, Singapore has primarily exported to Hong Kong, China, Malaysia, the United States, and Indonesia, while the majority of its imports have originated from China, Malaysia, Taiwan, the United States, and Japan.
The increasing contribution of import/export rate reflects the significance of foreign trade to Singapore’s economy. Prior to the outbreak of COVID-19 in 2020, Singapore’s bilateral trade growth between 2010 and 2019 was robust. Importantly, during this time period, export growth continuously outperformed that of bilateral commerce. Hence, the value of exports increased consistently from 2016 to 2019.
Using Time-series visualization tools, this article will reveal the impact of COVID-19 on the global economic and political dynamic in 2022.
Packages
The following packages are used for this project.
- tidyverse:
- readxl: This package makes it easy to get data out of Excel and into R. It has no external dependencies, so it’s easy to install and use on all operating systems. It is designed to work with tabular data. The easiest way to install the latest released version from CRAN is to install the whole tidyverse. Note that you will still need to load readxl explicitly, because it is not a core tidyverse package loaded via
library(tidyverse) - tidyr: Tidy data describes a standard way of storing data that is used wherever possible throughout the tidyverse. If you ensure that your data is tidy, you’ll spend less time fighting with the tools and more time working on your analysis.
- lubridate: Functions to work with date-times and time-spans: fast and user friendly parsing of date-time data, extraction and updating of components of a date-time (years, months, days, hours, minutes, and seconds), algebraic manipulation on date-time and time-span objects. The easiest way to get lubridate is to install the whole tidyverse.
- readxl: This package makes it easy to get data out of Excel and into R. It has no external dependencies, so it’s easy to install and use on all operating systems. It is designed to work with tabular data. The easiest way to install the latest released version from CRAN is to install the whole tidyverse. Note that you will still need to load readxl explicitly, because it is not a core tidyverse package loaded via
- plotly: is an R package for creating interactive web-based graphs via the open source JavaScript graphing library
plotly.js. - d3scatter: is an HTML R widget for interactive scatter plots visualization. It is based on the htmlwidgets R package and on the d3.js javascript library.
- ggbraid: ggbraid provides a new stat,
stat_braid(), that extends the functionality ofgeom_ribbon()to correctly fill the area between two alternating lines (or steps) with two different colors. ggbraid also provides a geom,geom_braid(), that wrapsgeom_ribbon()and usesstat_braid()by default. You can install the development version of ggbraid from GitHub with:
ggplot2: A system for ‘declaratively’ creating graphics, based on “The Grammar of Graphics”. You provide the data, tell ‘ggplot2’ how to map variables to aesthetics, what graphical primitives to use, and it takes care of the details.
- TimeSeries: This R package offers novel time series visualisations. It is based on
ggplot2and offersgeoms and pre-packaged functions for easily creating any of the offered charts. - hrbrthemes: A compilation of extra ‘ggplot2’ themes, scales and utilities, including a spell check function plot label fields and an overall emphasis on typography.
- ggiraph: is a tool that allows you to create dynamic ggplot graphs. This allows you to add tooltips, hover effects and JavaScript actions to the graphics.
- TimeSeries: This R package offers novel time series visualisations. It is based on
tmap: With the tmap package, thematic maps can be generated with great flexibility. The syntax for creating plots is similar to that of
ggplot2, but tailored to maps.CGPfunctions: Miscellaneous functions useful for teaching statistics as well as actually practicing the art. They typically are not new methods but rather wrappers around either base R or other packages. This package is used to create slope graph in this project.
Use the code chunk below to call the packages required for this project.
packages = c('readxl', 'datawizard', 'crosstalk', 'tidyr', 'lubridate','tidyverse', 'plotly', 'd3scatter','tidyquant', 'ggbraid', 'ggTimeSeries', 'CGPfunctions', 'tmap', 'ggplot2', 'hrbrthemes', 'ggiraph', 'ggrepel')
for(p in packages){
if(!require(p,character.only = T)){
install.packages(p)
}
library(p,character.only = T)
}2.1 Data Preparation
Merchandise Trade provided by Department of Statistics, Singapore (DOS) is used. Pay attention to the fact that the data is in xlsx format with several tabs. As a result, we will manage using functions from the readxl packages.
Step 1. Checking the number of sheets it contains
To list all sheets in an excel spreadsheet, we utilize the readxl package’s function excel sheet.
excel_sheets("data/data.xlsx")[1] "Content" "T1" "T2"
Step 2. Importing data
The readxl package’s read_xlsx() function is used in the code chunk below to import the data worksheet of our data workbook into R.
T1 <- read_xlsx("data/data.xlsx", sheet = "T1")
T2 <- read_xlsx("data/data.xlsx", sheet = "T2")Step 3. Transpose the fat table to long table
Gather takes multiple columns and collapses into key-value pairs, duplicating all other columns as needed. You use gather() when you notice that you have columns that are not variables. This function is under tidyr package.
T1 <- gather(T1, "MonthYear", "ImportValue", -`Data Series`)
T2 <- gather(T2, "MonthYear", "ExportValue", -`Data Series`)| Data Series | MonthYear | ImportValue |
|---|---|---|
| Total Merchandise Imports (Thousand Dollars) | 2022 Dec | 49869770 |
| America (Million Dollars) | 2022 Dec | 6901.5 |
| Asia (Million Dollars) | 2022 Dec | 33611.7 |
| Europe (Million Dollars) | 2022 Dec | 7541.8 |
| Oceania (Million Dollars) | 2022 Dec | 1399.9 |
| Data Series | MonthYear | ExportValue |
|---|---|---|
| Total Merchandise Exports (Thousand Dollars) | 2022 Dec | 55000084 |
| America (Million Dollars) | 2022 Dec | 6217.5 |
| Asia (Million Dollars) | 2022 Dec | 39734.8 |
| Europe (Million Dollars) | 2022 Dec | 4924.4 |
| Oceania (Million Dollars) | 2022 Dec | 3034.8 |
Step 4. Convert MonthYear column to date format
For our time series analysis, we then convert the date time to the date format using the ym function from the lubridate package.
T1$`MonthYear` <- ym(T1$`MonthYear`)
T2$`MonthYear` <- ym(T2$`MonthYear`)
# Convert ImportValue column to numeric format
T1$`ImportValue` <- as.numeric(T1$`ImportValue`)
T2$`ExportValue` <- as.numeric(T2$`ExportValue`)Step 5. Separate region and country
Notice that the country column contains both country and region-level information. To prevent misleading analysis, we have created the field Level to distinguish between the Region and Country levels.
# =================== Import =================== #
Region <- T1 %>%
filter(grepl('Million', `Data Series`)) %>%
rename("Region" = "ImportValue")
Country <- T1 %>%
filter(grepl('Thousand', `Data Series`)) %>%
rename("Country" = "ImportValue")
Import <- full_join(Region, Country, by = join_by(`Data Series`, `MonthYear`))
Import <- gather(Import , "Level", "ImportValue", -`Data Series`, -`MonthYear`)
# =================== Export =================== #
Region <- T2 %>%
filter(grepl('Million', `Data Series`)) %>%
rename("Region" = "ExportValue")
Country <- T2 %>%
filter(grepl('Thousand', `Data Series`)) %>%
rename("Country" = "ExportValue")
Export <- full_join(Region, Country, by = join_by(`Data Series`, `MonthYear`))
Export <- gather(Export , "Level", "ExportValue", -`Data Series`, -`MonthYear`)Step 6. Filter year from 2016 and rename column
Because we are focusing on the impact of the Covid epidemic event, we only filter data from 2016 to 2022.
Import <- Import %>%
filter(`MonthYear`> as.Date("2015-12-01")) %>%
rename(`Country` = `Data Series`)
Export <- Export %>%
filter(`MonthYear`> as.Date("2015-12-01")) %>%
rename(`Country` = `Data Series`)Step 7. Merge Import and Export into one table
wide <- full_join(Import, Export, by = join_by(`Country`, `MonthYear`,`Level`))
wide <- wide %>%
mutate("Diff" = ImportValue-ExportValue) %>%
mutate("Total" = ImportValue+ExportValue)
wide$`Country` <- str_replace(wide$`Country`, "Mainland China", "China")
wide$`Country` <- str_replace_all(wide$`Country`, " \\(|Thousand Dollars|\\)", "")
wide$`Country` <- str_replace_all(wide$`Country`, " \\(|Million Dollars|\\)", "")
long <- gather(wide , "Type", "Value", -`Country`, -`MonthYear`,-`Level`)And now we have both a wide table and a long table prepared for analysis.
Table Wide : Merchandise Imports/Export By Region/Market, Monthly
| Country | MonthYear | Level | ImportValue | ExportValue | Diff | Total |
|---|---|---|---|---|---|---|
| America | 2022-12-01 | Region | 6901.5 | 6217.5 | 684.0 | 13119.0 |
| Asia | 2022-12-01 | Region | 33611.7 | 39734.8 | -6123.1 | 73346.5 |
| Europe | 2022-12-01 | Region | 7541.8 | 4924.4 | 2617.4 | 12466.2 |
| Oceania | 2022-12-01 | Region | 1399.9 | 3034.8 | -1634.9 | 4434.7 |
| Africa | 2022-12-01 | Region | 414.9 | 1088.6 | -673.7 | 1503.5 |
Table Long : Merchandise Imports/Export By Region/Market, Monthly
| Country | MonthYear | Level | Type | Value |
|---|---|---|---|---|
| America | 2022-12-01 | Region | ImportValue | 6901.5 |
| Asia | 2022-12-01 | Region | ImportValue | 33611.7 |
| Europe | 2022-12-01 | Region | ImportValue | 7541.8 |
| Oceania | 2022-12-01 | Region | ImportValue | 1399.9 |
| Africa | 2022-12-01 | Region | ImportValue | 414.9 |
3 Visualizations
3.1 Uncover the Singapore Bi-lateral trend over Covid outbreak
We begin with a ribbon plot to illustrate the overall pattern of Singapore international trade over time. The function ggbraid helps distinguish between trade surplus and trade deficit by filling the region between two alternating lines with two different colors.
This code is related to creating a line plot of Singapore’s bi-lateral trade trend from 2016 to 2022.
First, the wide dataset is subsetted to select only the total merchandise imports and exports for Singapore at the country level. The resulting data is grouped by month and year.
Next, the singaporeribbon dataset is created by selecting and gathering the necessary columns from the singapore dataset. The drop_na() function is used to remove any rows with missing values.
Then, the hues variable is defined to assign colors for the line plot. A ggplot object p is created and geom_line() is used to plot the lines representing the import and export values. The labs() function is used to add a title, subtitle, and axis labels. The annotate() function is used to add vertical lines and text for significant events in the plot.
Next, the geom_braid() function is used to add ribbons to the plot showing the difference between imports and exports for each month. The resulting plot is stored in p1.
Lastly, ggplotly() function is used to convert the ggplot object p to an interactive plotly plot.
Step 1. Prepare data for line plot of Singapore
Code
singapore <- wide %>%
subset((Country == "Total Merchandise Imports"|Country == "Total Merchandise Exports")
& Level == "Country") %>%
group_by(MonthYear)
singaporeribbon <- singapore %>%
select(`Country`, `MonthYear`, `Level`, `ImportValue`, `ExportValue`) %>%
gather("Type", "Value", -`Country`, -`MonthYear`, -`Level`) %>%
drop_na()Step 2. Prepare data for line plot of Singapore
Code
hues <- scales::hue_pal()(2)
p <- ggplot() +
geom_line(aes(`MonthYear`, `Value`, linetype = `Type`),
data = singaporeribbon,
show.legend = FALSE) +
labs(title = "Singapore Bi-lateral Trade Trend",
subtitle = "2016-2022",
x = 'Month Year',
y = 'Trade Value'
) +
annotate("segment",
x = as.Date("2020-01-01"),
xend = as.Date("2020-01-01"),
y = 0,
yend = 70000000,
colour = "red") +
annotate("text",
label = "Covid outbreak",
x = as.Date("2020-12-01"),
y=25000000,
color = "red") +
annotate("text",
x = as.Date("2018-06-01"),
y = 60000000, size = 4,
label = "Export > Import",
hjust = 0,
color = hues[1])
p1 <- p+
geom_braid(aes(`MonthYear`,
ymin = `ImportValue`,
ymax = `ExportValue`,
fill = `ImportValue`>`ExportValue`),
show.legend = FALSE,
data = singapore,
alpha = 0.6,
method = 'line')
p1
ggplotly(p)
As a result of the COVID-19 epidemic, Singapore’s international commerce dropped in 2020
As per the analysis of the bilateral trend from 2016 to 2022, it can be observed that Singapore has a positive trade balance or trade surplus. This indicates that Singapore has been exporting more goods than it has been importing during this period. The trend was observed to be stable and strong from 2016 to 2019, where Singapore experienced a healthy growth in international trade. However, the growth began to weaken in 2019.
The year 2020 witnessed a significant decline in Singapore’s trade growth due to the outbreak of the COVID-19 pandemic in May. The pandemic had a profound impact on Singapore’s international trade as it caused disruptions in the supply chains, restrictions on the movement of goods and services, and a decline in consumer demand. As a result, the trade growth rate dropped dramatically before quickly returning to pre-pandemic levels.
Despite the pandemic’s impact, Singapore’s trade balance remained positive, indicating that the country continued to export more goods than it imported. It is noteworthy that Singapore has been taking measures to mitigate the impact of the pandemic on its trade activities, such as exploring new trade opportunities with emerging markets and increasing investment in technological advancements to enhance its trade capabilities. These efforts demonstrate Singapore’s resilience and commitment to sustaining a positive trade balance and driving its economic growth forward.
3.2 Merchandise trade performance with major trading partners
To illustrate the trade balance with all of Singapore’s trading partners, the bubble plot between import and export is chosen. The X-axis shows Singapore’s import value, while the Y-axis shows Singapore’s export value. Each bubble is colored differently depending on the country it represents.
The size of the bubbles indicates the total value of Singapore’s merchandise trade with the trading partner. If the bubble’s center point rises below the line, Singapore’s imports from the trade partner exceed Singapore’s exports. If the bubble’s center point falls beyond the line, Singapore’s exports to the trading partner exceed Singapore’s imports.
The graph is animated to emphasize the fluctuating equilibrium over time. Only major trading partners are depicted on the graph to reflect the effect of the key contributors.
This code is used to create an animated scatter plot that shows the merchandise trade performance between Singapore and its major trading partners, namely China, Malaysia, Taiwan, Hong Kong, and Indonesia from 2016 to 2022.
First, the data is filtered to include only the relevant countries using the subset() function. Then, the plot_ly() function from the plotly package is used to create the scatter plot. The x-axis represents the import value and the y-axis represents the export value. The color of each data point represents the country, and the size of each data point is proportional to the total trade value.
Next, the dline() function is defined to create a diagonal line that represents equal import and export values. The layout() function is then used to customize the plot’s title, subtitle, hover label, legend, x-axis, y-axis, width, and height. The showlegend argument is set to FALSE to hide the legend because the color of each data point already represents the country.
The animation_opts() function is used to define the duration and easing of the animation. The animation_slider() function is used to add a slider that allows the user to select the month-year to display.
Finally, the plot is stored in the fig object and can be displayed using fig. The plot can also be saved as an HTML file using the htmlwidgets::saveWidget() function.
Step 1. Create scatter plot with plotly
Code
# Plot scatter plot
scatter <- wide %>%
subset(Country == "China" | Country == "Malaysia" | Country == "Taiwan" | Country == "Hong Kong" | Country == "Indonesia" )
fig <- scatter %>%
plot_ly(
x = ~`ImportValue`,
y = ~`ExportValue`,
color = ~`Country`,
frame = ~as.character(`MonthYear`, format = "%Y-%m"),
size = ~`Total`,
sizes = c(1,10000),
text= ~paste("Country:",`Country`,
"\nImport Value:", `ImportValue`, " Thousand Dollars",
"\nExport Value:", `ExportValue`, " Thousand Dollars",
"\nTotal:", `Total`,
"\nMonth Year:", `MonthYear`),
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
)Step 2. Set up layout
Code
# Create the diagonal line
dline <- function(color = "steelblue") {
list(
type = "line",
yref = "paper",
xref = "paper",
y0 = 0, y1 = 1,
x0 = 0, x1 = 1,
line = list(color = color, dash="dot")
)
}
# Setup layout
fig <- fig %>%
layout(title = list(text="MERCHANDISE TRADE PERFORMANCE WITH MAJOR TRADING PARTNERS"),
subtitle = "2016-2022",
hoverlabel = list(align = "left"),
shapes = dline(),
legend = list(orientation = "h", y = 1, x = 0),
showlegend = FALSE,
xaxis = list(title="Import Value", range = list(0, 10000000)),
yaxis = list(title="Export Value", range = list(0, 10000000)),
width=650,
height=650
)Step 3. Set up animation
Code
fig <- fig %>%
animation_opts(
500, easing = "linear", redraw = FALSE
)
# Animation slider
fig <- fig %>% animation_slider(
currentvalue = list(prefix = "MONTH-YEAR :", font = list(color="red"))
)
figChina’s import and export volume declined sharply in the beginning of 2020
During December 2019 to February 2020, the China bubble shows a decline along the diagonal axis which suggests a substantial drop in both imports and exports from China within the specified period. However, it quickly bounced back thereafter. Similarly, Malaysia’s bubble followed a similar path to China’s, starting from December 2019, but it continued to decline until mid-2020. In May 2020, the impact of Indonesia is evident as there was a significant 25% reduction in overall trade volume.
When compared to other trading partners, the decline in Singapore’s exports to Hong Kong seems to be less affected. However, a rapid increase in exports to Hong Kong is evident in 2021.
We employ the ribbon chart once again to assess the impact of Covid-19 on Singapore’s most major trading partners.
Code
braid <- wide %>%
select(`Country`, `MonthYear`, `Level`, `ImportValue`, `ExportValue`) %>%
drop_na() %>%
subset(Country == "China")
ribbon <- gather(braid , "Type", "Value", -`Country`, -`MonthYear`, -`Level`)
braid2 <- wide %>%
select(`Country`, `MonthYear`, `Level`, `ImportValue`, `ExportValue`) %>%
drop_na() %>%
subset(Country == "Malaysia")
ribbon2 <- gather(braid2 , "Type", "Value", -`Country`, -`MonthYear`, -`Level`)
braid3 <- wide %>%
select(`Country`, `MonthYear`, `Level`, `ImportValue`, `ExportValue`) %>%
drop_na() %>%
subset(Country == "Taiwan")
ribbon3 <- gather(braid3 , "Type", "Value", -`Country`, -`MonthYear`, -`Level`)
braid4 <- wide %>%
select(`Country`, `MonthYear`, `Level`, `ImportValue`, `ExportValue`) %>%
drop_na() %>%
subset(Country == "Hong Kong")
ribbon4 <- gather(braid4 , "Type", "Value", -`Country`, -`MonthYear`, -`Level`)
braid5 <- wide %>%
select(`Country`, `MonthYear`, `Level`, `ImportValue`, `ExportValue`) %>%
drop_na() %>%
subset(Country == "Indonesia")
ribbon5 <- gather(braid5 , "Type", "Value", -`Country`, -`MonthYear`, -`Level`)
ggplot() +
geom_line(aes(`MonthYear`, `Value`, linetype = `Type`),
data = ribbon,
show.legend = FALSE) +
geom_braid(aes(`MonthYear`,
ymin = `ImportValue`,
ymax = `ExportValue`,
fill = `ImportValue`>`ExportValue`),
data = braid,
alpha = 0.6,
method = 'line',
show.legend = FALSE)+
labs(title = "Singapore trade balance trend with China",
x = 'Month Year',
y = 'Trade Value'
) +
annotate("rect",
xmin = as.Date("2020-01-01"),
xmax = as.Date("2022-12-01"),
ymin = 0,
ymax = 10000000,
alpha = .1,
fill = "yellow")
ggplot() +
geom_line(aes(`MonthYear`, `Value`, linetype = `Type`),
data = ribbon2,
show.legend = FALSE) +
geom_braid(aes(`MonthYear`,
ymin = `ImportValue`,
ymax = `ExportValue`,
fill = `ImportValue`>`ExportValue`),
data = braid2,
alpha = 0.6,
method = 'line',
show.legend = FALSE)+
labs(title = "Singapore trade balance trend with Malaysia",
x = 'Month Year',
y = 'Trade Value'
) +
annotate("rect",
xmin = as.Date("2020-01-01"),
xmax = as.Date("2022-12-01"),
ymin = 0,
ymax = 10000000,
alpha = .1,
fill = "yellow")+
annotate("text",
x = as.Date("2021-01-01"),
y = 2500000, size = 4,
label = "Import > Export",
hjust = 0,
color = hues[2])
ggplot() +
geom_line(aes(`MonthYear`, `Value`, linetype = `Type`),
data = ribbon3,
show.legend = FALSE) +
geom_braid(aes(`MonthYear`,
ymin = `ImportValue`,
ymax = `ExportValue`,
fill = `ImportValue`<`ExportValue`),
data = braid3,
alpha = 0.6,
method = 'line',
show.legend = FALSE)+
labs(title = "Singapore trade balance trend with Taiwan",
x = 'Month Year',
y = 'Trade Value'
) +
annotate("rect",
xmin = as.Date("2020-01-01"),
xmax = as.Date("2022-12-01"),
ymin = 0,
ymax = 10000000,
alpha = .1,
fill = "yellow")+
annotate("text",
x = as.Date("2019-01-01"),
y = 1000000, size = 4,
label = "Import > Export",
hjust = 0,
color = hues[2])
ggplot() +
geom_line(aes(`MonthYear`, `Value`, linetype = `Type`),
data = ribbon4,
show.legend = FALSE) +
geom_braid(aes(`MonthYear`,
ymin = `ImportValue`,
ymax = `ExportValue`,
fill = `ImportValue`>`ExportValue`),
data = braid4,
alpha = 0.6,
method = 'line',
show.legend = FALSE)+
labs(title = "Singapore trade balance trend with Hong Kong",
x = 'Month Year',
y = 'Trade Value'
) +
annotate("rect",
xmin = as.Date("2020-01-01"),
xmax = as.Date("2022-12-01"),
ymin = 0,
ymax = 10000000,
alpha = .1,
fill = "yellow")+
annotate("text",
x = as.Date("2019-01-01"),
y = 9000000, size = 4,
label = "Export > Import",
hjust = 0,
color = hues[1])
ggplot() +
geom_line(aes(`MonthYear`, `Value`, linetype = `Type`),
data = ribbon5,
show.legend = FALSE) +
geom_braid(aes(`MonthYear`,
ymin = `ImportValue`,
ymax = `ExportValue`,
fill = `ImportValue`>`ExportValue`),
data = braid5,
alpha = 0.6,
method = 'line',
show.legend = FALSE)+
labs(title = "Singapore trade balance trend with Indonesia",
x = 'Month Year',
y = 'Trade Value'
) +
annotate("rect",
xmin = as.Date("2020-01-01"),
xmax = as.Date("2022-12-01"),
ymin = 0,
ymax = 10000000,
alpha = .1,
fill = "yellow")+
annotate("text",
x = as.Date("2019-01-01"),
y = 9000000, size = 4,
label = "Export > Import",
hjust = 0,
color = hues[1])




Singapore Bi-lateral trend with major trading partners
The ribbon chart conveys the same message as the bubble chart. In February 2020, a significant decline in imports and exports between Singapore and China could be recognized. In terms of import and export rates, trade between Singapore and China has been well balanced. In 2021, Singapore will likely export more to China.
Malaysia demonstrates an unexpected tendency. Prior to the start of Covid-19, commerce between Singapore and Malaysia was balanced. Since the Covid-19 outbreak, however, Singapore has had a trade deficit with Malaysia.
Covid-19 appears to have little effect on Singapore imports from Taiwan. Taiwan’s import volume keeps on growing steadily.
Export from Singapore to Hong Kong has a minimal effect, as there is no discernible change in trend, but the export rate is projected to rise in 2021.
Imports and exports with Indonesia decreased significantly at the beginning of 2020.
3.3 Observe trade dynamic of Singapore’s major trading partners in relative
The slope graph allows us to see how each country’s import and export dynamics change in relation to the other countries over time.
This code creates two slope plots to display the total import and export values for five countries (China, Malaysia, Taiwan, Hong Kong, and Indonesia) from 2016 to 2022.
The first step for both plots is to subset the original data frame to only include the five countries of interest, and then add columns for month and year extracted from the “MonthYear” column. The resulting data frame is then grouped by country and year, and the total import or export value is calculated for each group using the summarise() function.
After this, the data frame is manipulated to ensure that the “Year” column is ordered correctly and is a factor variable.
For the import plot, the newggslopegraph() function is used to create a slope plot with the year on the x-axis and the total import value on the y-axis. The plot is titled “Total Import per Year” with a subtitle of “2016-2022”, and the annotate() function is used to add a yellow rectangle highlighting the period from 2020 to 2022.
The same process is repeated for the export plot, with the only differences being the function and plot titles, and the addition of a yellow rectangle to highlight the same period from 2020 to 2022.
Step 1. Prepare data for slope graph
Code
# Import
slopeimport <- wide %>%
subset(Country == "China" | Country == "Malaysia" | Country == "Taiwan" | Country == "Hong Kong" | Country == "Indonesia" ) %>%
mutate(month = month(MonthYear)) %>%
mutate(year = year(MonthYear)) %>%
drop_na() %>%
group_by(Country, year) %>%
summarise(sumyear = sum(ImportValue)) %>%
mutate(Year = factor(year)) %>%
arrange(`sumyear`)
#Export
slopeexport <- wide %>%
subset(Country == "China" | Country == "Malaysia" | Country == "Taiwan" | Country == "Hong Kong" | Country == "Indonesia" ) %>%
mutate(month = month(MonthYear)) %>%
mutate(year = year(MonthYear)) %>%
drop_na() %>%
group_by(Country, year) %>%
summarise(sumyear = sum(ExportValue)) %>%
mutate(Year = factor(year)) %>%
arrange(`sumyear`)Step 2. Create slope plot
Code
# Create slope plot for import
p <- newggslopegraph(dataframe = slopeimport,
Times = `Year`,
Measurement = `sumyear`,
Grouping = `Country`,
Title = "Total Import per Year",
SubTitle = "2016-2022",
Caption = NULL)
p + annotate("rect",
xmin = "2020",
xmax = "2022",
ymin = -1,
ymax = 600000,
alpha = .1,
fill = "yellow")
# Create slope plot for export
p2 <- newggslopegraph(dataframe = slopeexport,
Times = `Year`,
Measurement = `sumyear`,
Grouping = `Country`,
Title = "Total Export per Year",
SubTitle = "2016-2022",
Caption = NULL)
p2 + annotate("rect",
xmin = "2020",
xmax = "2022",
ymin = -1,
ymax = 600000,
alpha = .1,
fill = "yellow")

Trade dynamic of Singapore’s major trading partners in relative
The import rankings have remained unchanged, with China maintaining its top position consistently. However, Singapore has increased its imports from three countries, including China, Malaysia, and Taiwan, since 2020.
On the export side, the ranking has also remained steady, with China remaining the top exporter. While China experienced a slowdown in export growth in 2019, it showed accelerated growth in 2021, much like Hong Kong. Malaysia and Indonesia, on the other hand, saw a significant drop in export volumes in 2020 before bouncing back in 2021.
3.4 Observing the dynamic of trade balance based on location
This code is creating an animated choropleth map using the tmap package in R.
First, the World data set is loaded, which contains the geographic information for countries. The select function is used to keep only the columns iso_a3, name, sovereignt, and geometry. The resulting data frame is stored in the map variable.
Then, the name and sovereignt columns in map are converted to character type using as.character.
Next, the full_join function is used to combine the map data with the wide data by matching the sovereignt column in map with the Country column in wide. The resulting data frame is stored in data_map_area. The drop_na function is then used to remove any rows with missing values.
The tmap_mode("view") sets the mode to view mode to enable interactive viewing of the map.
The tm_shape function is used to create a tmap object from the data_map_area data frame. The tm_polygons function is used to create the choropleth map by mapping the Diff variable to the color of the polygons.
The tm_facets function is used to create an animated map by grouping the data by the MonthYear column and setting free.coords = FALSE to keep the same scale across all frames.
Finally, the tmap_animation function is used to create an animated GIF of the choropleth map with a delay of 50 milliseconds between frames. The resulting GIF is saved as choropleth.gif.
Step 1. Prepare data for Choropleth map
Code
data("World")
map <- World %>%
select(iso_a3, name, sovereignt, geometry)
map$name <- as.character(map$name)
map$sovereignt <- as.character(map$sovereignt)Step 2. Create animated map
Code
data_map_area <- map %>%
full_join(wide, by = c('sovereignt' = 'Country')) %>%
drop_na()
tmap_mode("view")
choropleth <- tm_shape(data_map_area) +
tm_polygons("Diff") +
tm_facets(along = "MonthYear", free.coords = FALSE)
tmap_animation(choropleth , filename = "choropleth.gif", delay = 50)
3.5 Monitoring the relative trade balance dynamics of Singapore’s major trading partners
Heatmaps allow us to see the group’s auto-correlation and compare it to another group at the same time.
Step 1. Prepare data by selecting top difference between import and export
Code
heatmap <- wide %>%
drop_na() %>%
group_by(Country) %>%
mutate(totaldiff = sum(Diff)) %>%
arrange(totaldiff) %>%
subset(Country == "China" | Country == "Malaysia" | Country == "Taiwan" | Country == "Hong Kong" | Country == "Indonesia" ) Step 2. Plot heatmap
Code
p <- heatmap %>%
ggplot(aes(x = MonthYear, y = reorder(Country,totaldiff), fill= Diff)) +
geom_tile_interactive(tooltip = c(paste( "Country:", heatmap$Country,
"\n Import:", heatmap$ImportValue,
"\n Export:", heatmap$ExportValue,
"\n Balance:" , -heatmap$Diff,
"\n Month:", heatmap$MonthYear))) +
scale_fill_distiller(palette = "Spectral") +
theme_ipsum() +
geom_tile() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=2))+
labs(title = "Relative trade balance dynamics of Singapore's major trading partners", x="", y="") +
annotate("segment",
x = as.Date("2020-01-01"),
xend = as.Date("2020-01-01"),
y = 0,
yend = 6,
colour = "red") +
annotate("text",
label = "Covid outbreak",
x = as.Date("2020-06-01"),
y=2,
color = "red")
girafe(
ggobj = p,
width_svg = 15,
height_svg = 3
)Insights from heatmap
The difference in color tone between Hong Kong and the other countries stand out as the trading relationship between Singapore and Hong Kong is highly surplus. The darker blue color of Hong Kong, which began in early 2021, reflects the quicker rise of export volume in comparison to import volume.
Contrary to Hong Kong, Taiwan reflects the outstanding deficit balance. The gradual darkening of the red shade over time for Taiwan represents the continuing increase of import volume over export.
3.6 Singapore-China trading pattern
Step 1: Deriving month and year fields
Code
cycle <- wide
cycle$month <- month(cycle$`MonthYear`)
cycle$year <- year(cycle$`MonthYear`)Step 2: Extracting the target country
Code
cycle <- cycle %>%
subset(`Country`== "China") %>%
drop_na()Step 3: Plotting the cycle plot
Code
ggplot() +
geom_line(data=cycle, aes(x=year, y=ImportValue, group=month), colour= "steelblue") +
geom_line(data=cycle, aes(x=year, y=ExportValue, group=month), colour= "#ec5954") +
facet_grid(~month) +
labs(title = "Singapore-China trading pattern",
subtitle = "2016-2022") +
ylab("Trading Volume") +
theme(plot.title = element_text(size=15),
axis.text.x = element_text(size = 10, angle = 90),
axis.text.y = element_text(size = 10),
strip.text = element_text(size = 10))
Singapore-China trade
From the cycle plot, we note that each month follows a similar pattern, with a dip in 2019-2020 and a rise beginning in 2021.
4 Interactive Dashboard
An interactive dashboard has been created to assist users in determining the impact of Covid-19 on Singapore bi-lateral commerce. The dashboard includes user-selected country and month input for time specification.
Code
# Prepare data for dashboard
line <- long %>%
subset(Type == "ImportValue"|Type == "ExportValue")
# Building interactive filters
d <- highlight_key(line)
filter_tools <- htmltools::div(
filter_select(id = "filter",
label = "Select Country",
sharedData = d,
group = ~Country,
multiple=FALSE),
filter_slider(id = "period",
label = "Select period",
sharedData = d,
column = ~year(MonthYear),
width = "100%"),
filter_slider(id = "value",
label = "Select Value",
sharedData = d,
column = ~Value,
width = "100%"),
filter_checkbox(id = "variable",
label = "Select variable",
sharedData = d,
group = ~Type,
inline = FALSE))
vline <- function(x = 0, color = "steelblue") {
list(
type = "line",
y0 = 0, y1 = 1,
yref = "paper",
x0 = x, x1 = x,
line = list(color = color, dash="dot")
)
}
# plotting interactive scatter plot using plotly
p <- plot_ly(data=d,
type= "scatter",
mode= "line",
x= ~MonthYear,
y= ~Value,
color= ~Type,
colors= "Accent",
# fill = 'tonexty',
text= ~paste("Country:",`Country`,
"\nMonth Year:", `MonthYear`,
"\nType:",`Type`)) %>%
layout(title = list(text="<b>Import/Export trend by country</b>"),
hoverlabel = list(align = "left"),
legend = list(orientation = "h", y = 1, x = 0),
shapes = vline("2020"),
xaxis = list(title="Month Year"),
yaxis = list(title="Value"))
gg <- highlight(p, "plotly_selected")
# Using crosstalk bscols to put all 3 elements (filter, scatter plot, datatable) together.
crosstalk::bscols(filter_tools,gg,DT::datatable(d, class= "display",
filter=list(position="top", clear=FALSE),
options=list(pageLength = 10,scrollY = TRUE,
iDisplayLength = 25)),
widths = c(4, 8, 12),
annotations = list(caption = "Data from Department of Statistics, Singapore (DOS)"))Code
function filter_default() {
document.getElementById("filter").getElementsByClassName("selectized")
[0].selectize.setValue("China", false);
}
window.onload = filter_default;5 Conclusion
Covid-19 has had a tremendous impact on the international trade of Singapore. For each country, the impact occurs at a different period and with a distinct magnitude. In 2021, the pattern, however, returned to steady growth.
Code
# Building interactive filters
# d <- highlight_key(ribbon)
# # d2 <- highlight_key(braid)
#
# filter_tools <- htmltools::div(
# filter_select(id = "country",
# label = "Select Country",
# sharedData = d,
# group = ~Country,
# multiple=FALSE),
#
# filter_slider(id = "period",
# label = "Select period",
# sharedData = d,
# column = ~year(MonthYear),
# width = "100%"))
#
# # plotting interactive scatter plot using plotly
# p <- ggplot() +
# geom_line(aes(`MonthYear`, `Value`, linetype = `Type`), data = ribbon)
# # +
# # geom_braid(aes(`MonthYear`,
# # ymin = `ImportValue`,
# # ymax = `ExportValue`,
# # fill = `ImportValue`>`ExportValue`),
# # data = braid, alpha = 0.6) +
# # guides(linetype = "none", fill = "none")
#
#
# gg <- highlight(p, "plotly_selected")
#
# # Using crosstalk bscols to put all 3 elements (filter, scatter plot, datatable) together.
# crosstalk::bscols(filter_tools, gg, widths = c(4, 8))